﻿using AngleExpress.service;
using AngleExpress.software;
using AngleExpress.utils;
using AngleExpress.viewmodel;
using AngleExpress.web;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace AngleExpress
{
    /// <summary>
    /// Content.xaml 的交互逻辑
    /// </summary>
    public partial class Content : Window
    {
        List<CustomerInfo> customerInfos;
        ContentViewModel viewModel;
        readonly string userID;
        bool isLogout = false;
        SoftwareInfo selectWebsite;
        readonly List<NotifyMsg> notifyList = new List<NotifyMsg>();
        readonly CancellationTokenSource pollingTokenSource;
        string ipAddress;

        readonly Dictionary<string, ISoftware> SoftwareHandlers = new Dictionary<string, ISoftware>
        {
            { "baishi-desktop-01", new BaiShiExpress() },
            { "shentong-desktop-01", new ShenTongExpress() },
            { "yunda-desktop-01", new YunDaCall() },
            { "yuantong-desktop-01", new YuanTongExpress() },
            { "yunda-desktop-02", new YunDaVpn() },
            {"yunda-desktop-03",new YunDaNewVpn() },
            {"cs-desktop-02",new ShoeCustomerService() },
            {"cs-desktop-01",new ShoelaceAssistor () },
            {"cs-desktop-03",new DuoKai() }
        };

        readonly Dictionary<string, string> WebsiteHandlers = new Dictionary<string, string>
        {
            { "baishi-web-01", "OpenBaishiXieHe" },
            { "baishi-web-02", "OpenBaishiZhangGui" },
            { "baishi-web-03", "OpenBaishiCrm" },
            { "baishi-web-04", "OpenBaishi123" },

            { "shentong-web-01", "OpenWangDianGuanJia" },
            { "yunda-web-01", "OpenYunDaYunZhiXing" },
            { "yunda-web-02", "OpenYunDaMoHe" },
            { "yunda-web-03", "OpenSmilePlan" },
            { "yunda-web-04","OpenYunDaMoHe" },

            { "suning-web-01", "OpenSuNingExpress" },
            { "zhongtong-web-01", "OpenZhongTongExpress" },
            {"yewu-web-01","OpenAngelExpress" },
            {"jitu-web-01","OpenJituExpress" },
            
        };

        readonly Dictionary<WebType, WebOpener> WebOpeners = new Dictionary<WebType, WebOpener>
        {
            { WebType.Chrome, new ChromeWebOpener() },
            { WebType.Edge, new EdgeWebOpener() },
            { WebType.Firefox, new FireFoxWebOpener() },
            {WebType.Qihu360,new QihuWebOpener() }
        };

        public Content(string userID, string username,int joinDay,string proxyCustomerInfo)
        {
            InitializeComponent();
            this.userID = userID;
            InitCustomerInfos(proxyCustomerInfo);
            InitViewModel(username, joinDay);
            //this.Closing += Content_Closing;
            pollingTokenSource = new CancellationTokenSource();
            launchNotifyPolling();
            if (string.IsNullOrEmpty(userID))
            {
                Utils.ShowError("用户标识id有误,请联系管理员");
            }
        }

        private void Content_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (isLogout)
            {
                pollingTokenSource.Cancel();
                foreach (WebOpener wo in WebOpeners.Values)
                    wo.Dispose();
            }
            else
            {
                MessageBoxResult result = MessageBox.Show("退出前会关闭已打开的浏览器,确实退出吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
                if (result.Equals(MessageBoxResult.OK))
                {
                    pollingTokenSource.Cancel();
                    foreach (WebOpener wo in WebOpeners.Values)
                        wo.Dispose();
                }
                else
                {
                    e.Cancel = true;
                }
            }


        }

        private void InitCustomerInfos(string infoStr)
        {
            string serviceUrl = System.Configuration.ConfigurationManager.AppSettings["ServiceUrl"];
            if (string.IsNullOrEmpty(serviceUrl))
            {
                //Utils.ShowError("读取配置文件信息失败!请检查配置文件是否正确");
                //Application.Current.Shutdown();
                serviceUrl = Global.ServiceUrl;
            }
            try
            {
                customerInfos = JsonConvert.DeserializeObject<List<CustomerInfo>>(infoStr);
                foreach (var customer in customerInfos)
                {
                    foreach (var web in customer.webList)
                    {
                        if (string.IsNullOrEmpty(web.sysIcon))
                            web.sysIcon = "/images/empty.jpg";
                        else if (!web.sysIcon.StartsWith("http"))
                            web.sysIcon = serviceUrl + web.sysIcon;
                    }
                    foreach (var desktop in customer.sysList)
                    {
                        if (string.IsNullOrEmpty(desktop.sysIcon))
                            desktop.sysIcon = "/images/empty.jpg";
                        else if (!desktop.sysIcon.StartsWith("http"))
                            desktop.sysIcon = serviceUrl + desktop.sysIcon;
                    }
                }
            }
            catch (Exception)
            {
                Utils.ShowError("解析服务端信息异常");
                return;
            }
        }

        void InvokeWebOpener(WebType driverType, string methodName, object[] args)
        {
            popUp.IsOpen = false;
            viewModel.Loading = true;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    Type t = Type.GetType("AngleExpress.web.WebOpener");
                    MethodInfo method = t.GetMethod(methodName);
                    WebOpener instance = WebOpeners[driverType];
                    method.Invoke(instance, args);
                }
                catch (System.Reflection.TargetInvocationException e)
                {
                    HandleWebOpenException(e, driverType);
                }
            }).ContinueWith(task =>
            {
                this.Dispatcher.Invoke(() =>
                {
                    viewModel.Loading = false;
                });
            });
        }

        void HandleWebOpenException(System.Reflection.TargetInvocationException e, WebType webType)
        {
            string errMsg;
            if (e.InnerException is DriverException)
            {
                var autoUpdate = new AutoUpdate.Program();
                if (webType == WebType.Chrome)
                {
                    string chromeVersion = autoUpdate.getGoogleVer();
                    errMsg = "请在默认位置安装64位"+chromeVersion+"版本谷歌浏览器";
                }
                else if (webType == WebType.Firefox)
                {
                    string firfoxVersion = autoUpdate.getFireFoxVer();
                    errMsg = "请在默认位置安装64位"+ firfoxVersion + "版本火狐浏览器";
                }
                else if (webType == WebType.Qihu360)
                {
                    string qihuVersion = autoUpdate.get360Ver();
                    errMsg = "请在默认位置安装内核版本为"+ qihuVersion + "的360极速浏览器";
                }
                else
                {
                    string edgeVersion = autoUpdate.getEdgeVer();
                    errMsg = "请在默认位置安装64位"+ edgeVersion + "版本Microsoft Edge浏览器";
                }
            }
            else
            {
                errMsg = e.InnerException.Message;
            }
            this.Dispatcher.Invoke(() =>
            {
                Utils.ShowError(errMsg);
            });
        }


        void InitViewModel(string userName, int joinDay)
        {
            viewModel = new ContentViewModel();
            viewModel.JoinDay = joinDay;
            viewModel.UserName = userName;
            viewModel.Version = new AutoUpdate.Program().localVersion();
            foreach (var customer in customerInfos)
                viewModel.ProxyUsers.Add(new ProxyUser { ProxyUserName = customer.name, ID = customer.id, Selected = false });

            if (customerInfos.Count > 0)
            {
                var firstCustomer = customerInfos[0];
                SwitchViewModal(firstCustomer, out string errMsg);
                this.DataContext = viewModel;
                if (errMsg != "")
                    Utils.ShowWarn(errMsg);
            }

        }

        private void ProxyUser_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            string customerID = btn.Tag.ToString();
            var selectCustomer = customerInfos.Where(c => c.id == customerID).FirstOrDefault();
            if (selectCustomer == null)
            {
                Utils.ShowError("软件异常");
                return;
            }

            SwitchViewModal(selectCustomer, out string errMsg);
            if (errMsg != "")
                Utils.ShowError(errMsg);
        }

        private void SwitchViewModal(CustomerInfo customer, out string errMsg)
        {
            errMsg = "";
            Dictionary<string, SoftwareGroup> groupDict = new Dictionary<string, SoftwareGroup>();

            try
            {
                foreach (var appInfo in customer.sysList)
                {
                    if (appInfo.sysName.Length < 2)
                    {
                        errMsg += String.Format("项目名称【{0}】太短,无法分组;", appInfo.sysName);
                        continue;
                    }

                    var appGroupName = appInfo.sysName.Substring(0, 2);
                    if (!groupDict.ContainsKey(appGroupName))
                        groupDict[appGroupName] = new SoftwareGroup() { GroupName = appGroupName };

                    groupDict[appGroupName].Softwares.Add(new SoftwareInfo()
                    {
                        SoftwareName = appInfo.sysName,
                        UserName = appInfo.loginName,
                        Password = appInfo.password,
                        OtherParam = appInfo.number,
                        Category = ProgramCategory.DeskTop,
                        IconUrl = appInfo.sysIcon,
                        Code = appInfo.flag,
                        SoftwareID=appInfo.sysId
                    }) ;
                }
                foreach (var webInfo in customer.webList)
                {
                    if (webInfo.sysName.Length < 2)
                    {
                        errMsg += String.Format("项目名称【{0}】太短,无法分组;", webInfo.sysName);
                        continue;
                    }

                    var appGroupName = webInfo.sysName.Substring(0, 2);
                    if (!groupDict.ContainsKey(appGroupName))
                        groupDict[appGroupName] = new SoftwareGroup() { GroupName = appGroupName };

                    groupDict[appGroupName].Softwares.Add(new SoftwareInfo()
                    {
                        SoftwareName = webInfo.sysName,
                        UserName = webInfo.loginName,
                        Password = webInfo.password,
                        OtherParam = webInfo.number,
                        Category = ProgramCategory.Web,
                        IconUrl = webInfo.sysIcon,
                        Code = webInfo.flag,
                        SoftwareID = webInfo.sysId
                    }) ;
                }
            }
            catch (Exception e)
            {
                errMsg = "解析数据异常,请联系管理员！" + e.Message;
                return;
            }

            foreach (var proxyUser in viewModel.ProxyUsers)
            {
                if (proxyUser.ID == customer.id)
                    proxyUser.Selected = true;
                else
                    proxyUser.Selected = false;
            }

            viewModel.SoftwareGroups.Clear();
            foreach (var group in groupDict)
            {
                viewModel.SoftwareGroups.Add(group.Value);
            }
            viewModel.Name = customer.name;
            viewModel.Phone = customer.mobile;
            viewModel.CompanyName = customer.companyName;
        }

        private void Software_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            SoftwareInfo info = btn.Tag as SoftwareInfo;

            if (info.Category == ProgramCategory.DeskTop)
            {
                
                OpenDesktopClient(info.Code, info.UserName, info.Password,info.OtherParam);
                userClickRecord(info.SoftwareID, ProgramCategory.DeskTop);
                //韵达vpn闹不了,直接显示用户名密码
                if (info.Code == "yunda-desktop-02")
                {
                    Infos infoWindow = new Infos("韵达VPN", info.UserName, info.Password);
                    infoWindow.Owner = this;
                    infoWindow.ShowDialog();
                }
                if (info.Code == "yunda-desktop-03")
                {
                    Infos infoWindow = new Infos("韵达VPN", info.UserName, info.Password);
                    infoWindow.Owner = this;
                    infoWindow.ShowDialog();
                }
            }
            else
            {
                selectWebsite = info;
                Console.WriteLine("赋值:" + selectWebsite.SoftwareName);
                popUp.IsOpen = true;
            }
        }

        private void OpenDesktopClient(string appCode, string usename, string password,string otherParam)
        {
            if (!SoftwareHandlers.ContainsKey(appCode))
            {
                Utils.ShowError("没有集成此软件，请在后台核对软件标识");
                return;
            }
            ISoftware software = SoftwareHandlers[appCode];

            if ( software.needLogin() && (string.IsNullOrEmpty(usename) || string.IsNullOrEmpty(password)))
            {
                if (MessageBoxResult.OK != MessageBox.Show("系统没有分配账号或者密码,仍然要打开吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information,
                    MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly))
                {
                    return;
                }
            }

            viewModel.Loading = true;
            Task.Run(() => {
                try
                {
                    software.OpenSoftware(usename, password,otherParam);
                }
                catch (Exception excep)
                {
                    Console.WriteLine(excep.StackTrace);
                    TextLog.Add(excep.Message);
                    TextLog.Add(excep.StackTrace);
                    this.Dispatcher.BeginInvoke(new Action<string>(msg =>
                    {
                        Utils.ShowError(msg);
                    }), excep.Message);
                    
                }
            }).ContinueWith(t => {
                viewModel.Loading = false;
            });
        }

        private void OpenWebSite(object sender, RoutedEventArgs e)
        {
            int tag = Convert.ToInt32((sender as Button).Tag);

            WebType webType = (WebType)tag;

            if (webType != WebType.Chrome && webType != WebType.Firefox && webType != WebType.Edge && webType != WebType.Qihu360)
            {
                Utils.ShowError("没有集成此浏览器,请联系开发者");
                return;
            }

            if (!WebsiteHandlers.ContainsKey(selectWebsite.Code))
            {
                Utils.ShowError("没有收录此网站，请在后台核对网站名称");
                return;
            }

            var methodName = WebsiteHandlers[selectWebsite.Code];

            if (string.IsNullOrEmpty(selectWebsite.UserName) || string.IsNullOrEmpty(selectWebsite.Password))
            {
                if (MessageBoxResult.OK != MessageBox.Show("系统没有分配账号或者密码,仍然要打开吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information,
                    MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly))
                {
                    return;
                }
            }
            InvokeWebOpener(webType, methodName, new object[] { selectWebsite.UserName, selectWebsite.Password ,selectWebsite.OtherParam});
            userClickRecord(selectWebsite.SoftwareID, ProgramCategory.Web);
        }


        private void Logout(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            //MessageBoxResult result = MessageBox.Show("退出前会关闭已打开的浏览器,确实退出吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
            //if (result.Equals(MessageBoxResult.OK))
            //{
                isLogout = true;
                MainWindow main = new MainWindow();
                main.Show();
                this.Close();
            //}
        }

        private void popUp_Closed(object sender, EventArgs e)
        {
            Console.WriteLine("置空:" + selectWebsite.SoftwareName);
            selectWebsite = null;
        }

        private async void userClickRecord(string softwareID, ProgramCategory category)
        {
            try {
                if (string.IsNullOrEmpty(ipAddress))
                {
                    ipAddress = await IpFinder.GetIP();
                }

                _ = Service.Instance().PostUseRecord(userID, softwareID, (int)category, ipAddress);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
            }
            
        }

        private void launchNotifyPolling() {

            _ = Task.Run(async() =>
              {
                  while (true)
                  {
                      if (pollingTokenSource.Token.IsCancellationRequested)
                      {
                          return;
                      }
                      NotifyMsgResult result = await Service.Instance().GetNotifyMsg(userID);
                      if (result.errMsg != null)
                      {
                          TextLog.Add("轮询通知失败:" + result.errMsg);
                          Thread.Sleep(5000);
                          continue;
                      }
                      foreach (NotifyInfo info in result.data)
                      {
                          if (notifyList.Where(n => n.ID == info.id).Count() == 0)
                          {
                              notifyList.Add(new NotifyMsg()
                              {
                                  ID = info.id,
                                  Title = info.oaNotify.title,
                                  Content = info.oaNotify.content,
                                  CreateTime = info.oaNotify.createDate.Substring(0,16)
                              });
                          }
                      }
                      viewModel.NotifyCount = notifyList.Count.ToString();
                      Thread.Sleep(5000);
                  }
                  
              });
            
        }

        private void OpenNotifyList(object sender, RoutedEventArgs e)
        {
            Notify notify = new Notify(notifyList,(string notifyID)=> {
                var item = notifyList.FirstOrDefault( n => {
                    return n.ID == notifyID; 
                });
                if (item != null)
                {
                    notifyList.Remove(item);
                    viewModel.NotifyCount = notifyList.Count.ToString();
                }
                _ = Service.Instance().UpdateNotifyRead(notifyID);
            });
            notify.Owner = this;
            notify.ShowDialog();
        }

        private void Button_Click_Wechat(object sender, RoutedEventArgs e)
        {
            new WeChat().OpenSoftware(null,null,null);
        }

        private void Button_Click_DingDing(object sender, RoutedEventArgs e)
        {
            new DingTalk().OpenSoftware(null, null, null);
        }

        private async void Version_Click(object sender, RoutedEventArgs e)
        {
            bool hasNewVersion;
            try {
                hasNewVersion = await new AutoUpdate.Program().hasNewVersion();
            }
            catch(Exception ex)
            {
                Utils.ShowError(ex.Message);
                return;
            }

            MessageBoxResult result;
            if (hasNewVersion)
            {
                result = Utils.ShowQuestion("发现新版本，是否更新？更新前将关闭当前窗口");
            }
            else
            {
                result= Utils.ShowQuestion("已是最新版本,仍要更新吗？更新前将关闭当前窗口");
            }

            if (result == MessageBoxResult.Yes)
            {
                if(!File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AutoUpdate.exe")))
                {
                    Utils.ShowError("找不到升级程序");
                    return;
                }
                ProcessStartInfo info = new ProcessStartInfo();
                info.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
                info.FileName = "AutoUpdate.exe";
                info.UseShellExecute = true;
                Process.Start(info);
            }
        }

        private void Detail_Click(object sender, RoutedEventArgs e)
        {
            var autoUpdate = new AutoUpdate.Program();
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("各浏览器支持版本如下");
            sb.Append("谷歌浏览器:");
            sb.AppendLine(autoUpdate.getGoogleVer());
            sb.Append("Edge浏览器:");
            sb.AppendLine(autoUpdate.getEdgeVer());
            sb.Append("火狐浏览器:");
            sb.AppendLine(autoUpdate.getFireFoxVer());
            sb.Append("360急速浏览器:");
            sb.AppendLine(autoUpdate.get360Ver());
            Utils.ShowInfo(sb.ToString());
        }
    }

    public enum WebType
    {
        Chrome,
        Firefox,
        Edge,
        Qihu360
    }

}
